package cn.broadsense.thrid.utils;


import cn.broadsense.common.exception.ServiceException;
import cn.broadsense.thrid.api.DaHuaTokenRepository;
import cn.broadsense.thrid.constant.DaHuaApiUrlConstant;
import cn.broadsense.thrid.enums.ResultStatusEnum;
import cn.broadsense.thrid.param.BaseParam;
import cn.broadsense.thrid.param.SecondAuthRequest;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 获取大华接口 token
 *
 * @author pengxin
 * @date 2022-08-04 12:28
 */
@Slf4j
public class DaHuaHttpUtils {

    /**
     * 获取token
     *
     * @param url
     * @param userName
     * @param password
     * @return
     */
    public static JSONObject getToken(String url, String userName, String password) {
        try {

            String param = "{userName: \"" + userName + "\", clientType: \"web\"}";
            // 第一次鉴权
            url = url + "/zhcs/apiserve/smc-ac/accounts/authorize";
            String firstResponseBody = HttpRequest.post(url).body(param).execute().body();
            log.info("第一次授权：{}", firstResponseBody);
            JSONObject jsonObject = JSONObject.parseObject(firstResponseBody);
            String randomKey = jsonObject.getString("randomKey");
            String realm = jsonObject.getString("realm");
            String encryptType = jsonObject.getString("encryptType");
            if (StrUtil.isNotBlank(randomKey) && StrUtil.isNotBlank(realm) && StrUtil.isNotBlank(encryptType)) {
                SecondAuthRequest secondAuthRequest = new SecondAuthRequest();
                secondAuthRequest.setClientType("web");
                secondAuthRequest.setEncryptType(encryptType);
                secondAuthRequest.setRandomKey(randomKey);
                secondAuthRequest.setRealm(realm);
                secondAuthRequest.setUserName(userName);
                secondAuthRequest.setPassword(SecondAuthRequest.encryptPassword(userName, secondAuthRequest.getRealm(), password, true));
                secondAuthRequest.setSignature(SecondAuthRequest.encryptSignature(userName, secondAuthRequest.getRealm(), secondAuthRequest.getPassword(), secondAuthRequest.getRandomKey()));
                // 第二次鉴权
                String secondResponseBody = HttpRequest.post(url).body(JSON.toJSONString(secondAuthRequest)).execute().body();
                log.info("第二次授权：{}", secondResponseBody);
                JSONObject secondJsonObject = JSONObject.parseObject(secondResponseBody);
                return secondJsonObject;
            }
        } catch (Exception e) {
            log.error("获取级联平台token发生异常: {}", e.getStackTrace());
            return null;
        }
        return null;
    }


    /**
     * 获取C系列token
     *
     * @param url
     * @param userName
     * @param password
     * @param ip
     * @return
     */
    public static String getCToken(String url, String userName, String password, String ip) throws Exception {
        JSONObject param = new JSONObject();
        param.put("userName", userName);
        param.put("clientType", "winpc");
        param.put("ipAddress", ip);
        String firstResponseBody = HttpRequest.post(url + "auth/thirdAuth/account").body(param.toJSONString()).execute().body();
        log.info("第一次交互结果：{}", firstResponseBody);
        JSONObject firstResult = JSONObject.parseObject(firstResponseBody);
        LoginSecond loginSecond = new LoginSecond();
        loginSecond.setUserName(userName);
        loginSecond.setClientType("winpc");
        loginSecond.setRandomKey(firstResult.getString("randomKey"));
        loginSecond.setEncryptType(firstResult.getString("encryptType"));
        String signature = loginSecond.calcSignature(password, firstResult.getString("realm"));
        loginSecond.setSignature(signature);
        //第二次交互
        String body = HttpRequest.post(url + "auth/thirdAuth/account").body(JSONObject.toJSONString(loginSecond)).execute().body();
        log.info("第二次交互结果：{}", body);
        return body;
    }


    public static String keepAliveCToken(String url, String token) {
        String content = "{\"token\":\"" + token + "\"}";
        String body = HttpRequest.put(url + "/videoService/accounts/token/keepalive").body(content).execute().body();
        return body;
    }


    /***
     *
     * 平台token保活
     * @param token
     * @param url 请求地址
     *
     * @return
     * */
    public static boolean tokenKeepalive(String url, String token) {
        try {
            String param = "{token: \"" + token + "\"}";
            String responseBody = HttpRequest.post(url + "/smc-ac/accounts/token/keepalive")
                    .header("X-Subject-Token", token).body(JSON.toJSONString(param)).execute().body();
            JSONObject jsonObject = JSONObject.parseObject(responseBody);
            if (jsonObject != null && "200".equals(jsonObject.getString("code"))) {
                log.error("平台token保活成功");
                return true;
            } else {
                log.error("平台token保活失败");
                return false;
            }
        } catch (Exception e) {
            log.error("平台token保活发生异常： {}", e.getStackTrace());
            return false;
        }
    }


    /**
     * post 请求
     *
     * @param token
     * @param request
     * @return
     */
    public static <T> T postRest(String token, BaseParam request) {
        try {
            HttpRequest httpRequest = HttpRequest.post(request.getUrl());
            //请求头
            return buildParamResult(token, request, httpRequest);
        } catch (Exception e) {
            log.error("调用接口失败:{}", e);
            throw new ServiceException("调用大华接口失败 失败信息：" + e.getMessage());
        }
    }

    /**
     * put 请求
     *
     * @param token
     * @param request
     * @param <T>
     * @return
     */
    public static <T> T putRest(String token, BaseParam request) {
        try {
            HttpRequest httpRequest = HttpRequest.put(request.getUrl());
            return buildParamResult(token, request, httpRequest);
        } catch (Exception e) {
            log.error("调用接口失败");
            throw new ServiceException("调用大华接口失败 失败信息：" + e.getMessage());
        }
    }


    /**
     * put 请求
     *
     * @param token
     * @param request
     * @param <T>
     * @return
     */
    public static <T> T deleteRest(String token, BaseParam request) {
        try {
            HttpRequest httpRequest = HttpRequest.delete(request.getUrl());
            return buildParamResult(token, request, httpRequest);
        } catch (Exception e) {
            log.error("调用接口失败");
            throw new ServiceException("调用大华接口失败 失败信息：" + e.getMessage());
        }
    }

    /**
     * get 请求
     *
     * @param token
     * @param request
     * @return
     */
    public static <T> T getRest(String token, BaseParam request) {
        return getRest(token, request, 0);
    }

    /**
     * get请求
     *
     * @param token
     * @param request
     * @param retryCount
     * @param <T>
     * @return
     */
    public static <T> T getRest(String token, BaseParam request, int retryCount) {
        try {
            HttpRequest httpRequest = HttpRequest.get(request.getUrl());
            log.info("请求地址：{}", request.getUrl());
            //请求头
            Map<String, String> headerMap = new HashMap<>(16);
            headerMap.put(DaHuaApiUrlConstant.TOKEN_KEY, token);
            httpRequest.addHeaders(headerMap);
            //校验参数
            request.checkParam();
            long beginTime = System.currentTimeMillis();
            HttpResponse execute = httpRequest.execute();
            int status = execute.getStatus();
            //未授权
            if (ResultStatusEnum.UNAUTHORIZED.getCode() == status && retryCount < 4) {
                DaHuaTokenRepository tokenRepository = SpringUtil.getBean(DaHuaTokenRepository.class);
                String dhCToken = tokenRepository.getDhCToken();
                if (dhCToken.equals(token)) {
                    String dhToken = tokenRepository.getDhCToken(true);
                    return getRest(dhToken, request, retryCount + 1);
                } else {
                    String dhToken = tokenRepository.getDhCToken(true);
                    return getRest(dhToken, request, retryCount + 1);
                }
            }
            long endTime = System.currentTimeMillis();
            log.info("接口请求花费时间：{}", endTime - beginTime);
            return buildResult(request, execute);
        } catch (Exception e) {
            log.error("调用接口失败");
            throw new ServiceException("调用大华接口失败 失败信息：" + e.getMessage());
        }
    }

    /**
     * 构建参数
     *
     * @param token
     * @param request
     * @param httpRequest
     * @param <T>
     * @return
     */
    private static <T> T buildParamResult(String token, BaseParam request, HttpRequest httpRequest) {
        return buildParamResult(token, request, httpRequest, 0);
    }

    /**
     * 构建参数
     *
     * @param token
     * @param request
     * @param httpRequest
     * @param retryCount  重试次数 最多重试3次
     * @param <T>
     * @return
     */
    private static <T> T buildParamResult(String token, BaseParam request, HttpRequest httpRequest, int retryCount) {
        //请求头
        Map<String, String> headerMap = new HashMap<>(16);
        headerMap.put(DaHuaApiUrlConstant.TOKEN_KEY, token);
        headerMap.put("Content-type", "application/json");
        httpRequest.addHeaders(headerMap);
        //校验参数
        request.checkParam();
        //添加忽略参数
        SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
        filter.getExcludes().addAll(request.getIgnoreList());
        String param = JSONObject.toJSONString(request);
        long beginTime = System.currentTimeMillis();
        log.info("接口请求地址：{}", httpRequest.getUrl());
        log.info("接口请求参数：{}-重试次数：{}", param,retryCount);
        HttpResponse execute = httpRequest.body(param).execute();
        int status = execute.getStatus();
        //未授权
        if (ResultStatusEnum.UNAUTHORIZED.getCode() == status && retryCount < 4) {
            DaHuaTokenRepository tokenRepository = SpringUtil.getBean(DaHuaTokenRepository.class);
            String dhCToken = tokenRepository.getDhCToken();
            if (dhCToken.equals(token)) {
                String dhToken = tokenRepository.getDhCToken(true);
                return buildParamResult(dhToken, request, httpRequest, retryCount + 1);
            } else {
                String dhToken = tokenRepository.getDhToken(true);
                return buildParamResult(dhToken, request, httpRequest, retryCount + 1);
            }
        }
        long endTime = System.currentTimeMillis();
        log.info("接口请求花费时间：{}", endTime - beginTime);
        return buildResult(request, execute);
    }

    private static <T> T buildResult(BaseParam request, HttpResponse execute) {
        int status = execute.getStatus();
        String body = execute.body();
        log.info("接口返回状态码：{}", status);
        log.info("接口返回结果：{}", body);

        if (ResultStatusEnum.OK.getCode() == status) {
            if (JSONUtil.isTypeJSONArray(body)) {
                JSONArray data = JSONArray.parseArray(body);
                return (T) data.toJavaList(request.getResultClass());
            }
            return (T) JSONObject.parseObject(body, request.getResultClass());
        } else {
            String msg = "获取第三方数据失败";
            if (JSONUtil.isTypeJSON(body)) {
                JSONObject jsonObject = JSONObject.parseObject(body);
                msg = "状态码：" + jsonObject.getString("code") + "-错误信息：" + jsonObject.getString("message");
            } else {
                msg = ResultStatusEnum.getMsgByCode(status);
            }
            throw new ServiceException(msg);
        }
    }

    public static void main(String[] args) throws Exception {
        //getCToken("http://175.178.201.56:18314","53boshi","broadsense@2022","172.19.74.116");
        getToken("https://159.75.254.250:18320", "wbj", "admin123456");

    }

}
